xpath数据解析
xpath解析
安装 :pip install lxml
解析原理
html标签是以树状的形式进行展示,实例化一个etree对象且把待解析的页面源码数据加载到该对象中,调用etree对象的xpath方法
结合着不同形式的xpath表达式进行标签定位和数据提取.
实例化etree对象:
etree.parse("filename"):将本地html文档加载到该对象中
etree.HTML(page_text):网站获取的页面数据加载到该对象
标签定位
最左侧的/:如果xpath表达式最左侧是以/开头则表示该xpath表达式一定要从根标签开始定位指定标签(相当于绝对路径,从根目录开始)
非最左侧的/:表示一个层级
非最左侧的//:表示多个层级
最左侧的//:xpath表达式可以从任意位置进行标签定位
属性定位:tagName[@attrName="value"]
索引定位:tag[index]:索引从1开始
取文本
/text() 取标签的直系文本内容
//text()标签下所有的文本内容
取属性:@attrNmae
基本使用
test.html
<html lang="en"> <head> <meta charset="UTF-8" /> <title>测试bs4</title> </head> <body> <div> <p>百里守约</p> </div> <div class="song"> <p>李清照</p> <p>王安石</p> <p>苏轼</p> <p>柳宗元</p> <a href="http://www.song.com/" title="赵匡胤" target="_self"> <span>this is span</span> 宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a> <a href="" class="du">总为浮云能蔽日,长安不见使人愁</a> <img src="http://www.baidu.com/meinv.jpg" alt="" /> </div> <div class="tang"> <ul> <li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li> <li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li> <li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li> <li><a href="http://www.sina.com" class="du">杜甫</a></li> <li><a href="http://www.dudu.com" class="du">杜牧</a></li> <li><b>杜小月</b></li> <li><i>度蜜月</i></li> <li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li> </ul> </div> </body> </html>
使用示例
from lxml import etree headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36", } tree = etree.parse("./test.html") # 放本地test.html文件名称 # print(tree.xpath("//title")) # 相对路径 # 属性定位 # print(tree.xpath("//div[@class='tang']")) # 索引定位:索引下标从1开始 # print(tree.xpath("//div[3]")) # /表示一个层级,//表示多个层级 # 下面两种写法获取的结果都一样 # print(tree.xpath("//div[@class='tang']/ul/li")) # print(tree.xpath("//div[@class='tang']//li")) # 获取指定标签中直系的文本内容,返回的是列表 # print(tree.xpath("//a[@id='feng']/text()")[0]) # 获取标签下所有的文本内容 # /text()获取标签的直系文本内容 # //text()获取标签下所有的文本内容 # print(tree.xpath("//div[@class='song']/text()")) # print(tree.xpath("//div[@class='song']//text()")) # 获取指定标签的属性值 # print(tree.xpath("//a[@id='feng']/@href")[0])
实例1:
import requests from lxml import etree headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36", } url = "https://www.qiushibaike.com/text/page/%d/" for page in range(1, 6): new_url = format(url % page) page_text = requests.get(new_url, headers=headers).text tree = etree.HTML(page_text) # 网页使用HTML print(tree) # 对象类型<Element html at 0x1cf694edf08> div_list = tree.xpath('//div[@class="col1 old-style-col1"]/div') for div in div_list: # 局部数据解析 author = div.xpath("./div[1]/a[2]/h2/text()")[0] content = div.xpath("./a[1]/div/span//text()") content = "".join(content) print(author, content)
实例2:爬取图片且保存到本地
import os import requests from urllib import request from lxml import etree dirName = 'imgLibs' if not os.path.exists(dirName): # 如果文件夹不存在就创建 os.mkdir(dirName) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36", } url = "https://pic.netbian.com/4kmeishi/" response = requests.get(url, headers=headers) response.encoding = 'gbk' page_text = response.text tree = etree.HTML(page_text) li_list = tree.xpath('//*[@id="main"]/div[3]/ul/li') for li in li_list: img_src = "{0}{1}".format("https://pic.netbian.com", li.xpath('./a/img/@src')[0]) img_name = li.xpath('./a/img/@alt')[0] + '.jpg' img_path = dirName + '/' + img_name # 拼接存储图片的路径 request.urlretrieve(img_src, img_path) print(img_name, "下载成功")